package com.hyt.it.ogt.kq.service.gov.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.lang.Opt;
import cn.hutool.core.util.StrUtil;
import cn.hutool.core.util.URLUtil;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.hyt.core.base.BaseEntity;
import com.hyt.core.base.BaseServiceImpl;
import com.hyt.core.constant.CommonConstant;
import com.hyt.core.util.RemoteUtil;
import com.hyt.core.util.UUIDUtils;
import com.hyt.exception.exception.BusinessLogicException;
import com.hyt.it.ogt.kq.common.config.GatherCenterConfig;
import com.hyt.it.ogt.kq.common.enums.GatherCenterImportStatusEnum;
import com.hyt.it.ogt.kq.service.gov.feign.kh.KhClient;
import com.hyt.it.ogt.kq.service.gov.feign.kh.model.AnalysisCenterFileParam;
import com.hyt.it.ogt.kq.service.gov.mapper.ExamAfterGatherMapper;
import com.hyt.it.ogt.kq.service.gov.model.entity.ExamAfterGather;
import com.hyt.it.ogt.kq.service.gov.model.entity.Task;
import com.hyt.it.ogt.kq.service.gov.model.entity.Time;
import com.hyt.it.ogt.kq.service.gov.model.param.GatherImportFileParam;
import com.hyt.it.ogt.kq.service.gov.model.param.GatherPageParam;
import com.hyt.it.ogt.kq.service.gov.model.param.GatherStatusUpdateParam;
import com.hyt.it.ogt.kq.service.gov.model.param.GatherSubjectNumUpdateParam;
import com.hyt.it.ogt.kq.service.gov.model.vo.GatherPageVO;
import com.hyt.it.ogt.kq.service.gov.service.IExamAfterGatherService;
import com.hyt.it.ogt.kq.service.gov.service.ITaskService;
import com.hyt.it.ogt.kq.service.gov.service.ITimeService;
import com.hyt.progress.service.ProgressManager;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.util.Optional;

/**
 * <p>
 * 考后汇总数据管理 服务实现类
 * </p>
 *
 * @author yanghuankun@talkweb.com.cn
 * @since 2023-12-22
 */
@Slf4j
@Service
public class ExamAfterGatherServiceImpl extends BaseServiceImpl<ExamAfterGatherMapper, ExamAfterGather> implements IExamAfterGatherService {

    @Resource
    GatherCenterConfig gatherCenterConfig;
    @Resource
    ITimeService iTimeService;
    @Resource
    ITaskService iTaskService;
    @Resource
    KhClient khClient;

    @Override
    public IPage<GatherPageVO> gatherPage(GatherPageParam param) {
        IPage<Time> timeIPage = iTimeService.lambdaQuery()
                .eq(BaseEntity::getDelFlag, Boolean.FALSE)
                .eq(Time::getTaskId, param.getTaskId())
                .orderByDesc(BaseEntity::getCreateDate)
                .page(param);

        IPage<GatherPageVO> gatherPageVOIPage = timeIPage.convert(data -> {
            Optional<ExamAfterGather> examAfterGatherOpt = this.lambdaQuery()
                    .eq(BaseEntity::getDelFlag, Boolean.FALSE)
                    .eq(ExamAfterGather::getTimeId, data.getId())
                    .orderByDesc(BaseEntity::getCreateDate)
                    .last(LIMIT_1)
                    .oneOpt();

            GatherPageVO gatherPageVO = examAfterGatherOpt.map(examAfterGather -> BeanUtil.toBean(examAfterGather, GatherPageVO.class))
                    .orElseGet(() -> {
                        return GatherPageVO.builder()
                                .timeId(data.getId())
                                .timeCode(data.getCode())
                                .timeName(data.getName())
                                .importStatus(CommonConstant.ZERO)
                                .build();
                    });

            return gatherPageVO;
        });
        return gatherPageVOIPage;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public String importFile(GatherImportFileParam param) {
        String zipFilePassword = Opt.ofNullable(param.getZipFilePassword())
                .filter(StrUtil::isNotBlank)
                .orElseGet(gatherCenterConfig::getZipFilePassword);

        Time time = Optional.ofNullable(param.getTimeId())
                .map(iTimeService::getById)
                .orElseThrow(() -> BusinessLogicException.getException(31432102, "未查询到批次信息"));

        Task task = Optional.ofNullable(time.getTaskId())
                .map(iTaskService::getById)
                .orElseThrow(() -> BusinessLogicException.getException(31432103, "未查询到任务信息"));

        String decode = URLUtil.decode(param.getZipFileUrl());
        String zipFileName = FileUtil.mainName(decode);

        String gatherId = UUIDUtils.newSortUUID();
        ExamAfterGather examAfterGather = new ExamAfterGather();
        examAfterGather.setOfficeId(task.getOfficeId());
        examAfterGather.setDeptId(task.getDeptId());
        examAfterGather.setTaskId(task.getId());
        examAfterGather.setTimeId(time.getId());
        examAfterGather.setTimeCode(time.getCode());
        examAfterGather.setTimeName(time.getName());
        examAfterGather.setImportFileName(zipFileName);
        examAfterGather.setImportFileUrl(param.getZipFileUrl());
        examAfterGather.setImportStatus(GatherCenterImportStatusEnum.STATUS_2.getCode());
        examAfterGather.setImportFilePassword(zipFilePassword);
        examAfterGather.setId(gatherId)
                .setCreateBy(param.getCurrentLoginUserId())
                .setCreateDate(LocalDateTime.now())
                .setUpdateBy(param.getCurrentLoginUserId())
                .setUpdateDate(LocalDateTime.now());
        boolean saveStatus = this.save(examAfterGather);

        AnalysisCenterFileParam analysisCenterFileParam = AnalysisCenterFileParam.builder()
                .gatherId(gatherId)
                .currentLoginUserId(param.getCurrentLoginUserId())
                .zipFileUrl(param.getZipFileUrl())
                .zipFilePassword(param.getZipFilePassword())
                .officeId(task.getOfficeId())
                .deptId(task.getDeptId())
                .taskId(task.getId())
                .taskName(task.getName())
                .taskBeginDate(task.getBeginDate())
                .taskEndDate(task.getEndDate())
                .timeId(time.getId())
                .timeName(time.getName())
                .timeBeginDate(time.getStartTime())
                .timeEndDate(time.getEndTime())
                .testClassify(task.getTestClassify())
                .build();
        String progressKey = RemoteUtil.getOrThrows(() -> khClient.analysisCenterFile(analysisCenterFileParam));
        return progressKey;
    }

    @Override
    public Boolean deleteGather(String id, String userId) {
        ExamAfterGather examAfterGather = this.getById(id);
        if (examAfterGather == null) {
            BusinessLogicException.throwException(31433104, "未查询到汇总任务");
        }
        if (examAfterGather != null && StrUtil.isBlank(examAfterGather.getTimeId())) {
            BusinessLogicException.throwException(31433105, "当前汇总任务未绑定批次");
        }

        // 删除考后的数据逻辑
        RemoteUtil.getOrThrows(() -> khClient.deleteAnalysisData(examAfterGather.getTimeId()));
        ProgressManager.updateProgressCurrent(80, "远程考后数据删除成功");

        boolean updateStatus = this.lambdaUpdate()
                .eq(BaseEntity::getId, id)
                .set(ExamAfterGather::getUpdateBy, userId)
                .set(ExamAfterGather::getUpdateDate, LocalDateTime.now())
                .set(ExamAfterGather::getDelFlag, Boolean.TRUE)
                .update();
        return updateStatus;
    }

    @Override
    public void gatherSubjectNumUpdate(GatherSubjectNumUpdateParam param) {
        this.lambdaUpdate()
                .eq(BaseEntity::getId, param.getGatherId())
                .set(ExamAfterGather::getSubjectNum, param.getSubjectNum())
                .set(ExamAfterGather::getUpdateBy, param.getCurrentLoginUserId())
                .set(ExamAfterGather::getUpdateDate, LocalDateTime.now())
                .update();
    }

    @Override
    public void gatherStatusUpdate(GatherStatusUpdateParam param) {
        this.lambdaUpdate()
                .eq(BaseEntity::getId, param.getGatherId())
                .set(ExamAfterGather::getImportStatus, param.getStatus())
                .set(ExamAfterGather::getUpdateBy, param.getCurrentLoginUserId())
                .set(ExamAfterGather::getUpdateDate, LocalDateTime.now())
                .update();
    }
}
